home *** CD-ROM | disk | FTP | other *** search
/ Atari Mega Archive 1 / Atari Mega Archive - Volume 1.iso / archiver / uux789.zoo / uud.c < prev    next >
C/C++ Source or Header  |  1989-07-06  |  12KB  |  573 lines

  1. /*
  2.  * Uud -- decode a uuencoded file back to binary form.
  3.  *
  4.  * From the Berkeley original, modified by MSD, RDR, JPHD & WLS.
  5.  * The Atari GEMDOS version compiled with MWC 2.x.
  6.  * The MSDOS version with TurboC.
  7.  * The Unix version with cc.
  8.  * this version is made: 25 Nov 1988.
  9.  */
  10.  
  11. /*
  12.  * Be sure to have the proper symbol at this point. (GEMDOS, MSDOS, UNIX...)
  13.  */
  14. /*
  15. #ifndef GEMDOS
  16. #define GEMDOS 1
  17. #endif
  18.  */
  19. #ifndef UNIX
  20. #define UNIX 1
  21. #endif
  22. /*
  23. #ifndef MSDOS
  24. #define MSDOS 1
  25. #endif
  26.  */
  27.  
  28. #ifdef GEMDOS
  29. #define SYSNAME "gemdos"
  30. #define SMALL 1
  31. #endif
  32. #ifdef MSDOS
  33. #define SYSNAME "msdos"
  34. #define SMALL 1
  35. #endif
  36. #ifdef UNIX
  37. #define SYSNAME "unix"
  38. #endif
  39.  
  40. #include <stdio.h>
  41.  
  42. #ifdef GEMDOS
  43. #include <osbind.h>
  44. #define Error(n)  { Bconin(2); exit(n); }
  45. #define WRITE      "wb"
  46. #else
  47. #define Error(n)  exit(n)
  48. #define WRITE      "w"
  49. #endif
  50.  
  51. #define loop    while (1)
  52.  
  53. extern FILE *fopen();
  54. extern char *strcpy();
  55. extern char *strcat();
  56.  
  57. char *getnword();
  58.  
  59. #define MAXCHAR 256
  60. #define LINELEN 256
  61. #define FILELEN 64
  62. #define NORMLEN 60    /* allows for 80 encoded chars per line */
  63.  
  64. #define SEQMAX 'z'
  65. #define SEQMIN 'a'
  66. char seqc;
  67. int first, secnd, check, numl;
  68.  
  69. FILE *in, *out;
  70. char *pos;
  71. char ifname[FILELEN], ofname[FILELEN];
  72. char *source = NULL, *target = NULL;
  73. char blank, part = '\0';
  74. int partn, lens;
  75. int debug = 0, nochk = 0, onedone = 0;
  76. int chtbl[MAXCHAR], cdlen[NORMLEN + 3];
  77.  
  78. main(argc, argv) int argc; char *argv[];
  79. {
  80.     int mode;
  81.     register int i, j;
  82.     char *curarg;
  83.     char dest[FILELEN], buf[LINELEN];
  84.  
  85.     if (argc < 2) {
  86.         format("Almost foolproof uudecode v3.4 (%s) 25-Nov-88\n",
  87.             SYSNAME);
  88.         format("\n");
  89.         format("Usage: uud [-n] [-d] [-s dir] [-t dir] input-file\n");
  90.         format("\n");
  91.         format("Option: -n -> No line sequence check\n");
  92.         format("Option: -d -> Debug/verbose mode\n");
  93.         format("Option: -s + Source directory for all input files\n");
  94.         format("  (MUST be terminated by directory separator)\n");
  95.         format("Option: -t + Target directory for all output files\n");
  96.         format("  (MUST be terminated by directory separator)\n");
  97.         format("If input-file is - then stdin is used as input-file\n");
  98.         Error(1);
  99.     }
  100.  
  101.     curarg = argv[1];
  102.     
  103.     while (curarg[0] == '-') {
  104.         if (((curarg[1] == 'd') || (curarg[1] == 'D')) &&
  105.             (curarg[2] == '\0')) {
  106.             debug = 1;
  107.         } else if (((curarg[1] == 'n') || (curarg[1] == 'N')) &&
  108.                (curarg[2] == '\0')) {
  109.             nochk = 1;
  110.         } else if (((curarg[1] == 't') || (curarg[1] == 'T')) &&
  111.                (curarg[2] == '\0')) {
  112.             argv++;
  113.             argc--;
  114.             if (argc < 2) {
  115.                 format("uud: Missing target directory.\n");
  116.                 Error(15);
  117.             }
  118.             target = argv[1];
  119.             if (debug)
  120.                 format("Target dir = %s\n",target);
  121.         } else if (((curarg[1] == 's') || (curarg[1] == 'S')) &&
  122.                (curarg[2] == '\0')) {
  123.             argv++;
  124.             argc--;
  125.             if (argc < 2) {
  126.                 format("uud: Missing source directory.\n");
  127.                 Error(15);
  128.             }
  129.             source = argv[1];
  130.             if (debug)
  131.                 format("Source dir = %s\n",source);
  132.         } else if (curarg[1] != '\0') {
  133.             format("uud: Unknown option <%s>\n", curarg);
  134.             Error(15);
  135.         } else
  136.             break;
  137.         argv++;
  138.         argc--;
  139.         if (argc < 2) {
  140.             format("uud: Missing file name.\n");
  141.             Error(15);
  142.         }
  143.         curarg = argv[1];
  144.     }
  145.  
  146.     if ((curarg[0] == '-') && (curarg[1] == '\0')) {
  147.         in = stdin;
  148.         strcpy(ifname, "<stdin>");
  149.     } else {
  150.         if (source != NULL) {
  151.             strcpy(ifname, source);
  152.             strcat(ifname, curarg);
  153.         } else
  154.             strcpy(ifname, curarg);
  155.         if ((in = fopen(ifname, "r")) == NULL) {
  156.             format("uud: Can't open %s\n", ifname);
  157.             Error(2);
  158.         }
  159.         numl = 0;
  160.     }
  161.  
  162. /*
  163.  * Set up the default translation table.
  164.  */
  165.     for (i = 0; i < ' '; i++) chtbl[i] = -1;
  166.     for (i = ' ', j = 0; i < ' ' + 64; i++, j++) chtbl[i] = j;
  167.     for (i = ' ' + 64; i < MAXCHAR; i++) chtbl[i] = -1;
  168.     chtbl['`'] = chtbl[' '];    /* common mutation */
  169.     chtbl['~'] = chtbl['^'];    /* an other common mutation */
  170.     blank = ' ';
  171. /*
  172.  * set up the line length table, to avoid computing lotsa * and / ...
  173.  */
  174.     cdlen[0] = 1;
  175.     for (i = 1, j = 5; i <= NORMLEN; i += 3, j += 4)
  176.         cdlen[i] = (cdlen[i + 1] = (cdlen[i + 2] = j));
  177. /*
  178.  * search for header or translation table line.
  179.  */
  180.     loop {    /* master loop for multiple decodes in one file */
  181.         partn = 'a';
  182.         loop {
  183.             if (fgets(buf, sizeof buf, in) == NULL) {
  184.                 if (onedone) {
  185.                     if (debug) format("End of file.\n");
  186.                     exit(0);
  187.                 } else {
  188.                     format("uud: No begin line.\n");
  189.                     Error(3);
  190.                 }
  191.             }
  192.             numl++;
  193.             if (strncmp(buf, "table", 5) == 0) {
  194.                 gettable();
  195.                 continue;
  196.             }
  197.             if (strncmp(buf, "begin", 5) == 0) {
  198.                 break;
  199.             }
  200.         }
  201.         lens = strlen(buf);
  202.         if (lens) buf[--lens] = '\0';
  203. #ifdef SMALL
  204.         if ((pos = getnword(buf, 3))) {
  205.             strcpy(dest, pos);
  206.         } else
  207. #else
  208.         if(sscanf(buf,"begin%o%s", &mode, dest) != 2)
  209. #endif
  210.         {
  211.             format("uud: Missing filename in begin line.\n");
  212.             Error(10);
  213.         }
  214.  
  215.         if (target != NULL) {
  216.             strcpy(ofname, target);
  217.             strcat(ofname, dest);
  218.         } else
  219.             strcpy(ofname, dest);
  220.  
  221.         if((out = fopen(ofname, WRITE)) == NULL) {
  222.             format("uud: Cannot open output file: %s\n", ofname);
  223.             Error(4);
  224.         }
  225.         if (debug) format("Begin uudecoding: %s\n", ofname);
  226.         seqc = SEQMAX;
  227.         check = nochk ? 0 : 1;
  228.         first = 1;
  229.         secnd = 0;
  230.         decode();
  231.         fclose(out);
  232. #ifdef UNIX
  233.         chmod(ofname, mode);
  234. #endif
  235.         onedone = 1;
  236.         if (debug) format("End uudecoding: %s\n", ofname);
  237.     }    /* master loop for multiple decodes in one file */
  238. }
  239.  
  240. /*
  241.  * Bring back a pointer to the start of the nth word.
  242.  */
  243. char *getnword(str, n) register char *str; register int n;
  244. {
  245.     while((*str == '\t') || (*str == ' ')) str++;
  246.     if (! *str) return NULL;
  247.     while(--n) {
  248.         while ((*str != '\t') && (*str != ' ') && (*str)) str++;
  249.         if (! *str) return NULL;
  250.         while((*str == '\t') || (*str == ' ')) str++;
  251.         if (! *str) return NULL;
  252.     }
  253.     return str;
  254. }
  255.  
  256. /*
  257.  * Install the table in memory for later use.
  258.  */
  259. gettable()
  260. {
  261.     char buf[LINELEN];
  262.     register int c, n = 0;
  263.     register char *cpt;
  264.  
  265.     for (c = 0; c <= MAXCHAR; c++) chtbl[c] = -1;
  266.  
  267. again:    if (fgets(buf, sizeof buf, in) == NULL) {
  268.         format("uud: EOF while in translation table.\n");
  269.         Error(5);
  270.     }
  271.     numl++;
  272.     if (strncmp(buf, "begin", 5) == 0) {
  273.         format("uud: Incomplete translation table.\n");
  274.         Error(6);
  275.     }
  276.     cpt = buf + strlen(buf) - 1;
  277.     *cpt = ' ';
  278.     while (*(cpt) == ' ') {
  279.         *cpt = 0;
  280.         cpt--;
  281.     }
  282.     cpt = buf;
  283.     while (c = *cpt) {
  284.         if (chtbl[c] != -1) {
  285.             format("uud: Duplicate char in translation table.\n");
  286.             Error(7);
  287.         }
  288.         if (n == 0) blank = c;
  289.         chtbl[c] = n++;
  290.         if (n >= 64) return;
  291.         cpt++;
  292.     }
  293.     goto again;
  294. }
  295.  
  296. /*
  297.  * copy from in to out, decoding as you go along.
  298.  */
  299.  
  300. decode()
  301. {
  302.     char buf[LINELEN], outl[LINELEN];
  303.     register char *bp, *ut;
  304.     register int *trtbl = chtbl;
  305.     register int n, c, rlen;
  306.     register unsigned int len;
  307.  
  308.     loop {
  309.         if (fgets(buf, sizeof buf, in) == NULL) {
  310.             format("uud: EOF before end.\n");
  311.             fclose(out);
  312.             Error(8);
  313.         }
  314.         numl++;
  315.         len = strlen(buf);
  316.         if (len) buf[--len] = '\0';
  317. /*
  318.  * Is it an unprotected empty line before the end line ?
  319.  */
  320.         if (len == 0) continue;
  321. /*
  322.  * Get the binary line length.
  323.  */
  324.         n = trtbl[*buf];
  325.         if (n >= 0) goto decod;
  326. /*
  327.  * end of uuencoded file ?
  328.  */
  329.         if (strncmp(buf, "end", 3) == 0) return;
  330. /*
  331.  * end of current file ? : get next one.
  332.  */
  333.         if (strncmp(buf, "include", 7) == 0) {
  334.             getfile(buf);
  335.             continue;
  336.         }
  337.         format("uud: Bad prefix line %d in file: %s\n",numl, ifname);
  338.         if (debug) format("Bad line =%s\n",buf);
  339.         Error(11);
  340. /*
  341.  * Sequence checking ?
  342.  */
  343. decod:        rlen = cdlen[n];
  344. /*
  345.  * Is it the empty line before the end line ?
  346.  */
  347.         if (n == 0) continue;
  348. /*
  349.  * Pad with blanks.
  350.  */
  351.         for (bp = &buf[c = len];
  352.             c < rlen; c++, bp++) *bp = blank;
  353. /*
  354.  * Verify if asked for.
  355.  */
  356.         if (debug) {
  357.             for (len = 0, bp = buf; len < rlen; len++) {
  358.                 if (trtbl[*bp] < 0) {
  359.                     format(
  360.     "Non uuencoded char <%c>, line %d in file: %s\n", *bp, numl, ifname);
  361.                     format("Bad line =%s\n",buf);
  362.                     Error(16);
  363.                 }
  364.                 bp++;
  365.             }
  366.         }
  367. /*
  368.  * All this just to